package com.stlcctv.POSSender;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class POSSenderActivity  {
    /** Called when the activity is first created. */
	public static final String DEBUG_TAG = "POSSender";
	
	private boolean		 m_bDVRConnect  = false;
	private Socket 		 m_Socket 		= null;
	private InputStream  m_StreamInput 	= null;
	private OutputStream m_StreamOutput = null;
	
	//Recv Thread 	
	public Thread 	m_Thread_Open 		= null;
	public Thread 	m_Thread_Recv 		= null;
	private boolean m_bThreadStop_Recv 	= true;
	
	private int	m_SendIndex = 0;
	//
	public boolean m_bDVRConnected = false;
//    @Override
//    public void onCreate(Bundle savedInstanceState) {
//        super.onCreate(savedInstanceState);
//        setContentView(R.layout.main);
//        
//        Log.i(DEBUG_TAG, "onCreate");
//		
//        m_Btn_Prepare = (Button)findViewById(R.id.btn_prepare);
//        m_Btn_Prepare.setOnClickListener(Click_Btn_Prepare);
//                
//        m_Btn_Trans_Start = (Button)findViewById(R.id.btn_trans_start);
//        m_Btn_Trans_Start.setOnClickListener(Click_Btn_Transaction_Start);
//        
//        m_Btn_POS_Send = (Button)findViewById(R.id.btn_pos_send);
//        m_Btn_POS_Send.setOnClickListener(Click_Btn_POS_Send);
//        
//		m_Thread_Open = new Thread(new OpenThread());
//		m_Thread_Open.start();
//		
//    }
    
//    private View.OnClickListener Click_Btn_Prepare = new View.OnClickListener() 
//	{
//		public void onClick(View v) {
//			// TODO Auto-generated method stub
//			Log.i(DEBUG_TAG,"m_Btn_Prepare clicked");
//			if(m_bDVRConnected == false)
//				Request_AliveCheck();
//		}
//	};
//	
//	private View.OnClickListener Click_Btn_Transaction_Start = new View.OnClickListener() 
//	{
//		public void onClick(View v) {
//			// TODO Auto-generated method stub
//			Log.i(DEBUG_TAG,"m_Btn_Trans_Start clicked");
//			Request_Transaction_Start();
//		}
//	};
//	
//	
//	private View.OnClickListener Click_Btn_POS_Send = new View.OnClickListener() 
//	{
//		public void onClick(View v) {
//			// TODO Auto-generated method stub
//			Log.i(DEBUG_TAG,"m_Btn_POS_Send clicked");
//			
//			Request_POS_Send();
//		}
//	};

	public String m_ipaddress;

	public int m_port;
	
	
//    public void onStart() {
//		super.onStart();
//		Log.i(DEBUG_TAG, "OnStart");
//	}

//	public void onRestart() {
//		super.onRestart();
//		Log.i(DEBUG_TAG, "onRestart");
//	}

//	public void onResume() {
//		super.onResume();
//	}
	
//	public void onPause() {
//		super.onPause();
//		StopRecvThread();
//		ReleaseSocket();
//		Log.i(DEBUG_TAG, "onPause");
//	}

//	public void onStop() {
//		super.onStop();
//		Log.i(DEBUG_TAG, "onStop");
//	}
	
//	@Override
//	protected void onDestroy() {
//		super.onDestroy();
//		
//		m_Btn_Prepare = null;
//		m_Btn_POS_Send = null;
//		m_Btn_Trans_Start = null;
//		Log.i(DEBUG_TAG, "onDestroy");
//
//		
//	}
    
	public class OpenThread implements Runnable 
	{
		public void run() 
		{
			TryConnect();
		}
	}
	public boolean TryConnect() 
	{
		boolean bRes = false;
		try 
		{
			//m_Socket = new Socket("192.168.10.67", 9020);
			m_Socket = new Socket(m_ipaddress, m_port);
			if (m_Socket == null) 
			{
				Log.i(DEBUG_TAG, "in TryConnect Socket Create Fail");
			} 
			else 
			{
				m_StreamInput  = m_Socket.getInputStream();
				m_StreamOutput = m_Socket.getOutputStream();
					
				Log.i(DEBUG_TAG, "Socket Create Success!");
				
				StartRecvThread();
				
				//Request Connect
				
				
				bRes = true;
			}
		} 
		catch (Exception e) 
		{		
			Log.i(DEBUG_TAG, "Socket Create Error Exception!" + e.getMessage());
		}
		return bRes;
	}
	public void ReleaseSocket()
	{
		try
		{
			if (m_StreamInput != null) {
				m_StreamInput.close();
				Log.i(DEBUG_TAG, "m_StreamInput.close()");
				m_StreamInput = null;
			}
			if (m_StreamOutput != null) {
				m_StreamOutput.close();
				Log.i(DEBUG_TAG, "m_StreamOutput.close()");
				m_StreamOutput = null;
			}
			if (m_Socket != null) {
				m_Socket.close();
				Log.i(DEBUG_TAG, "m_Socket.close()");				
				m_Socket = null;
			}
			Log.i(DEBUG_TAG, " Release Socket");	
		} 
		catch (NullPointerException ex) 
		{
			Log.i(DEBUG_TAG, "====== NullPointerException : " + ex.getMessage());	
			ex.printStackTrace();
		} 
		catch (IOException ex) 
		{
			Log.i(DEBUG_TAG, "====== IOException : " + ex.getMessage());	
		}
		
	}
	
	//================================================================================================
	public boolean StartRecvThread() 
	{
		Log.i(DEBUG_TAG, "StartRecvThread");
				
		m_bThreadStop_Recv = false;
		
		m_Thread_Recv = new Thread(new RecvThread());
		m_Thread_Recv.start();
		return true;
	}

	public void StopRecvThread() 
	{
		m_bThreadStop_Recv = true;
		try
		{
			Thread.sleep(1000);
		} 
		catch (NullPointerException ex) 
		{
			Log.i(DEBUG_TAG, "====== NullPointerException : " + ex.getMessage());
			ex.printStackTrace();
		} 
		catch (InterruptedException e) 
		{
			Log.i(DEBUG_TAG, "====== InterruptedException : " + e.getMessage());
		}
		Log.i(DEBUG_TAG, "StopRecvThread");

		m_Thread_Open = null;
		m_Thread_Recv = null;
	}
	
	
	class RecvThread implements Runnable 
	{
		protected int recvData(byte[] _data, int _len) 
		{
			int read_offset = 0;
			int will_read = _len;
			
			int read_unit = 0;
			int cur_read = 0;
			
			int result = 0;

			while(m_bThreadStop_Recv == false) 
			{
				try 
				{
					if (m_StreamInput == null) 
					{
						Log.i(DEBUG_TAG, "not yet create socket, so sleep 1 sec");
						
						Thread.sleep(1000);
						continue;
					}
					
					int AvailCnt = m_StreamInput.available();
					
					if (AvailCnt > 0) 
					{
						//Log.i(DEBUG_TAG, "recvData : AvailCnt " + AvailCnt);
						if (AvailCnt >= will_read) 	read_unit = will_read;
						else 						read_unit = AvailCnt;
						
						cur_read = m_StreamInput.read(_data, read_offset, read_unit);
						if (cur_read > 0) 
						{
							read_offset += cur_read;
							will_read -= cur_read;
							
							//Log.i(DEBUG_TAG, "read_offset : " + read_offset);
							
							if (read_offset >= _len) break;							
						}
					}
				}// End of try read
				// ==========================================================
				catch (IOException ex) 
				{
					Log.i(DEBUG_TAG, "han Recv IOException " + ex.getMessage());
				
					result = -1;
				} 
				catch (InterruptedException e) 
				{		
					Log.i(DEBUG_TAG,"in recvData : Interrupt Error Detect " + e.getMessage());
								
					result = -1;
				}

				// ==========================================================
				if (cur_read < 0) 
				{
					result = -1;
					break;
				}
			}// End of while(m_bThreadStop_Recv == false) 

			if(read_offset > 0) 
			{
				result = read_offset;
				Log.i(DEBUG_TAG, "result : " + result);
			}
			return result;
		}//End of int recvData(byte[] _data, int _len) 
		
		public void run() 
		{
			Log.i(DEBUG_TAG, "Recv Thread Start");
			byte[] respBuff = new byte[9];
			while(m_bThreadStop_Recv == false) 
			{
				//Log.i(DEBUG_TAG, "Recv Thread ");
				int recvCnt = recvData(respBuff, 9);
				if(recvCnt >= 9) 
				{
					byte crc_check = 0;
					
					byte start_code = respBuff[0];
					byte cmd_class = respBuff[1]; crc_check ^= respBuff[1];
					byte cmd_code  = respBuff[2]; crc_check ^= respBuff[2];
					short data_size = ByteArrayUtil.byteArrayToShort(respBuff, 3); crc_check ^= respBuff[3]; crc_check ^= respBuff[4];
					byte data_1 = respBuff[5]; crc_check ^= respBuff[5];
					byte data_2 = respBuff[6]; crc_check ^= respBuff[6];
					byte crc_recv = respBuff[7];
					byte end_code = respBuff[8];
					
					Log.i(DEBUG_TAG, "start_code [" + Integer.toHexString(start_code) + "]");
					Log.i(DEBUG_TAG, "cmd_class [" + Integer.toHexString(cmd_class) + "]");
					Log.i(DEBUG_TAG, "cmd_code [" + Integer.toHexString(cmd_code) + "]");
					Log.i(DEBUG_TAG, "dataSize [" + data_size + "]");
					Log.i(DEBUG_TAG, "data_1 [" + Integer.toHexString(data_1) + "]");
					Log.i(DEBUG_TAG, "data_2 [" + Integer.toHexString(data_2) + "]");
					Log.i(DEBUG_TAG, "crc_org [" + Integer.toHexString((int)crc_recv) + "]");
					Log.i(DEBUG_TAG, "crc_check [" + Integer.toHexString((int)crc_check) + "]");
					Log.i(DEBUG_TAG, "end_code [" + Integer.toHexString(end_code) + "]");
					
					if(crc_check == crc_recv)
					{
						if(cmd_class == 0x0A)
						{
							if(cmd_code == 0x06) //Ack
							{
								Log.i(DEBUG_TAG, "RESP : ACK!");
								if(data_1 == 0x0B)
								{
									if(data_2 == 0x0)//Alive Check Response
									{
										if(m_bDVRConnected == false) Request_ClearDisplay();
										else
											Log.i(DEBUG_TAG, "RESP : Alive Check!");
									}
									else if(data_2 == 0x04)// Clear Display Response
									{
										if(m_bDVRConnected == false) 
										{
											m_bDVRConnected = true;
											Log.i(DEBUG_TAG, "RESP : DVR Connected!");
										}
										else
											Log.i(DEBUG_TAG, "RESP : Clear Display!");
									}
									else if(data_2 == 0x01)// Response for confirming of POS Data
									{
										Log.i(DEBUG_TAG, "RESP : POS Data Recv OK!");
									}
								}
							}
							else if(cmd_code == 0x15) //Nack
							{
								Log.i(DEBUG_TAG, "RESP : NACK! ");
								if( (data_1 & 0xFF) == 0xFF)
								{
									if(data_2 == 0x0) Log.i(DEBUG_TAG, "Reason : Error CRC Send!");
									else if(data_2 == 0x01) Log.i(DEBUG_TAG, "Reason : Error Data Size!");
									else if(data_2 == 0x02) Log.i(DEBUG_TAG, "Reason : Unknown Command!");
									else if(data_2 == 0x03) Log.i(DEBUG_TAG, "Reason : Timeout!");
								}
							}
						}
						else
						{
							Log.i(DEBUG_TAG, "Unknown Command Class!");
						}
					}
					else
					{
						Log.i(DEBUG_TAG, "CRC Error!");
					}
					
						
				}
			}//End of thread while
			Log.i(DEBUG_TAG, "Recv Thread Finish");
			respBuff = null;
		}//End of run()
	}// End of class RecvThread implements Runnable 
	
	
	//===================================================================================================
	public synchronized int SendStreamData(byte[] _data, int _len) 
	{
		if (m_StreamOutput == null) return -1;
		int res = -1;

		int cur_send = 0;
		try 
		{
			m_StreamOutput.write(_data, 0, _len);
			Log.i(DEBUG_TAG,"Send Data - req _ length : " + _len);
		} 
		catch (IOException ex) 
		{
			Log.i(DEBUG_TAG,"Send Data Fail : " + ex.getMessage());
		}

		return res;
	}
	
	public void Request_AliveCheck() 
	{
		CommandComposer _Composer = new CommandComposer();

		_Composer.m_CmdCode  = _Composer.CMD_CODE_ALIVE_CHECK;
		
		byte[] sendBuffer = new byte[32];
		int bufSize = _Composer.MakeCommand_Simple(sendBuffer);
		SendStreamData(sendBuffer, bufSize);
		
		sendBuffer = null;
		_Composer = null;
		
	}
	public void Request_ClearDisplay() 
	{
		CommandComposer _Composer = new CommandComposer();
		
		_Composer.m_CmdCode  = _Composer.CMD_CODE_DISPLAY_CLEAR;
		
		byte[] sendBuffer = new byte[32];
		int bufSize = _Composer.MakeCommand_Simple(sendBuffer);
		SendStreamData(sendBuffer, bufSize);
		
		sendBuffer = null;
		_Composer = null;
		
	}
	
	public void Request_Transaction_Start(String ls_send) 
	{
		if(m_bDVRConnected == true)
		{
			CommandComposer _Composer = new CommandComposer();
			_Composer.m_CmdCode  = _Composer.CMD_CODE_TRANSACTION_START;
			byte[] sendBuffer = new byte[100];
			String pos_data = ls_send;
			int bufSize = _Composer.MakeCommand_POSSend(sendBuffer,pos_data,(short) pos_data.length());
			Log.i(DEBUG_TAG,"Send Data bufSize : " + bufSize);
			SendStreamData(sendBuffer, bufSize);
			
			sendBuffer = null;
			_Composer = null;
			pos_data = null;
		}
	}
	public void Request_POS_Send() 
	{
		if(m_bDVRConnected == true)
		{
			m_SendIndex++;
			CommandComposer _Composer = new CommandComposer();
			_Composer.m_CmdCode  = _Composer.CMD_CODE_POS_DATA;
			byte[] sendBuffer = new byte[100];
			String pos_data = "STL Android Test Data" + Integer.toString(m_SendIndex);
			
			int bufSize = _Composer.MakeCommand_POSSend(sendBuffer,pos_data,(short) pos_data.length());
			Log.i(DEBUG_TAG,"Send Data2 bufSize : " + bufSize);
			SendStreamData(sendBuffer, bufSize);
			
			sendBuffer = null;
			_Composer = null;
			pos_data = null;
		}
	}
	//===================================================================================================
}